package models;

import java.util.List;

import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import javax.persistence.UniqueConstraint;

import notifiers.Mails;
import controllers.Users;

import play.db.jpa.Model;
import play.libs.Mail;

@Entity
@Table(name = "Task_Users", uniqueConstraints = { @UniqueConstraint(columnNames = {
		"reviewer_id", "task_id" }) })
public class TaskUser extends Model {

	// as he needs to request
	// true means his request has been approved
	// false means his request is pending
	public boolean status;

	@ManyToOne
	@JoinColumn(name = "reviewer_id")
	public User reviewer;

	@ManyToOne
	@JoinColumn(name = "task_id")
	public Task task;

	public TaskUser(User reviewer, Task task) {
		this.reviewer = reviewer;
		this.task = task;
		this.status = false;
	}

	public TaskUser(User reviewer, Task task, boolean status) {
		this.reviewer = reviewer;
		this.task = task;
		this.status = status;
	}

	/**
	 * Accepts a review request to a certain task. If a reviewer is already
	 * assigned to that task, he's removed automatically and the new one is put
	 * 
	 * @param pendingReviewId
	 * 
	 * @return boolean
	 */
	public boolean acceptReviewRequest() {
		List<TaskUser> taskReviewers = this.task.taskReviewers;
		TaskUser taskReview = null;
		boolean found = false;
		for (int i = 0; i < taskReviewers.size(); i++) {
			if (taskReviewers.get(i).status == true) {
				taskReview = taskReviewers.get(i);
				found = true;
				break;
			}
		}
		if (found) {
			this.task.taskReviewers.remove(taskReview);
			taskReview.delete();
		}

		this.status = true;
		this.save();
		return true;

	}

	/**
	 * Rejects all the requests in the input list of pending requests for a
	 * specific task. Usually called once a reviewer is assigned to that task so
	 * that no more than one reviewer can review the task at the same time.
	 * 
	 * @param pendingTaskReviews
	 * @return boolean
	 */
	public boolean rejectPendingTaskReviewRequests(
			List<TaskUser> pendingTaskReviews) {
		for (int i = 0; i < pendingTaskReviews.size(); i++) {
			pendingTaskReviews.get(i).rejectReviewRequestHelper();
		}
		return true;
	}

	/**
	 * Rejects a review request to a certain task and removes the request from
	 * the system and notifies the requester.
	 * 
	 * @param pendingReviewId
	 * @return boolean
	 */

	public boolean rejectReviewRequestHelper() {
		this.delete();
		Long projectId = (Long) this.task.userStory.component.project
				.getEntityId(); // task may not always be associated to a user
		// story so this could give a null pointer
		// exception (Rawan)
		new Log((Long) this.getEntityId(), "TaskUser",
				"Request to review the task: \"" + this.task.description
						+ "\" rejected. A reviewer has been assigned.",
				projectId, " ").save();
		String subject = "Task Review Request";
		String msg = "Your request to review the task \""
				+ this.task.description
				+ "\" has been denied because another reviewer has been assigned.";
		new Notification((Long) this.reviewer.getEntityId(), subject,
				"You have been assigned to review a task.").save();
		Mail.send("coolsoft@SMT.com", this.reviewer.email, subject, msg);
		return true;

	}

	/**
	 * Calls the method rejectReviewRequestHelper then redirects to the task
	 * review requests page.
	 * 
	 * @param pendingReviewId
	 */
	public boolean rejectReviewRequest() {
		this.delete();
		return true;
	}
	/**
	 * creates a new model object TaskUser with status = false which indicates
	 * that the user has a pending request to review a task
	 * 
	 * @author Rana Ashraf
	 * @param taskId
	 * @param userId
	 * @return boolean
	 */
	public static boolean requestReviewTask(long taskId, long userId) {

		User reviewer = User.findById(userId);
		Task task = Task.findById(taskId);
		Project project = task.events.get(0).project;
		TaskUser tu = new TaskUser(reviewer, task).save();
	
		new Log(userId, (Long) tu.getEntityId(), "TaskUser",
				"requested to review the task", (Long) project.getEntityId(),
				" ").save();

		return true;
	}
}
